home *** CD-ROM | disk | FTP | other *** search
/ Amiga Collections: Various / DevDisk 65 (1989)(DevWare PD).zip / DevDisk 65 (1989)(DevWare PD).adf / prosuite / xtext.asm < prev    next >
Assembly Source File  |  1990-07-11  |  19KB  |  611 lines

  1.  
  2. * *** xtext.asm *************************************************************
  3. *
  4. * XText  --  The XText Routine
  5. * (from the FastText algorithms created in January, 1986)
  6. *   from Book 1 of the Amiga Programmers' Suite by RJ Mical
  7. *
  8. * Copyright (C) 1986, 1987, Robert J. Mical
  9. * All Rights Reserved.
  10. *
  11. * Created for Amiga developers.
  12. * Any or all of this code can be used in any program as long as this
  13. * entire copyright notice is retained, ok?  Thanks.
  14. *
  15. * The Amiga Programmer's Suite Book 1 is copyrighted but freely distributable.
  16. * All copyright notices and all file headers must be retained intact.
  17. * The Amiga Programmer's Suite Book 1 may be compiled and assembled, and the 
  18. * resultant object code may be included in any software product.  However, no 
  19. * portion of the source listings or documentation of the Amiga Programmer's 
  20. * Suite Book 1 may be distributed or sold for profit or in a for-profit 
  21. * product without the written authorization of the author, RJ Mical.
  22. * HISTORY       Name             Description
  23. * ------------  ---------------  -------------------------------------------
  24. * 27 Oct 86     RJ Mical >:-{)*  Translated this file.
  25. *
  26. * ***************************************************************************
  27.  
  28.     INCLUDE "xtext.i"
  29.  
  30.  
  31.     IFND    AZTEC ; If AZTEC not defined, do it the standard way
  32.     XDEF    _XText
  33.     XREF    _custom
  34.     XREF    _GfxBase
  35.     ENDC
  36.     IFD    AZTEC ; If AZTEC defined, do it the non-standard way (sigh)
  37.     PUBLIC    _XText
  38.     PUBLIC    _custom
  39.     PUBLIC    _GfxBase
  40.     ENDC
  41.  
  42.  
  43.  
  44. _XText:
  45. * ***************************************************************************
  46. * These FastText algorithms were created by =Robert J. Mical= in January 1986
  47. * Copyright (C) 1986, =Robert J. Mical=
  48. * All Rights Reserved
  49. *
  50. * This is my brute-force XText() routine.
  51. * It presumes many things about text:  that the characters come in
  52. * pairs, that the characters are 8-bits wide (this one is not easily 
  53. * undone), and more.
  54. *
  55. * The theory of operation here is that I will build a single plane of
  56. * normal characters (character data bits set, background bits clear)
  57. * in the Normal Text Plane, using the data from the Output Characters
  58. * Buffer.  As needed, I will invert this plane (character bits clear,
  59. * background bits set) into the Inverted Text Plane.  There's two other
  60. * globally accessible (pre-initialized) planes used:  an AllClearPlane plane
  61. * of all bits clear, and an AllSetPlane plane of all bits set.
  62. *
  63. * Using these four planes, I can construct a bitmap of all possible pen
  64. * settings for the foreground and background.  If corresponding bits
  65. * in the FgPen and BgPen are:
  66. *        -----      -----
  67. *          0       0        Use All Clear Plane
  68. *          0       1        Use Inverted Text Plane
  69. *          1       0        Use Normal Text Plane
  70. *          1       1        Use All Set Plane
  71. *
  72. * Note that if FgPen and BgPen are equal, I don't have to bother
  73. * constructing the Normal or Inverted Text Planes, since they'll
  74. * never be used.
  75. *
  76. * An optimization that evolves out of this fact is that you can fill a line
  77. * or part of a line of your text with spaces (blank characters) much more
  78. * quickly by setting the foreground pen equal to the background pen.  The
  79. * trick with this optimization is to not spend too much time detecting
  80. * whether or not an area of text is all blank, for you may lose the
  81. * increased performance during the handling of normal text lines.
  82. *
  83. * A further optimization is that I'm guessing that many text calls
  84. * will not require the inverted plane, so I won't make it until I 
  85. * discover that I need it.  If programmers follow the
  86. * Intuition-encouraged standard of pen 1 for foreground and pen 0
  87. * for background, then the bits are:  FgPen -- 00001
  88. *                                     BgPen -- 00000
  89. * In fact, if the text is *any* color against a background of zero,
  90. * this optimization works.
  91. *
  92. * For example, the plain PC monochrome text turns out to be pen 1 on
  93. * pen 0.  No need to invert here!
  94. *
  95. * So I won't bother constructing the inverted plane until I discover
  96. * that it's needed.  The cost of this is that I have to check a flag
  97. * once per time that I find an inverted bit plane is called for (6 times 
  98. * maximum (though of course Dale would say 8 times maximum)), and the 
  99. * savings is avoiding an unnecessary inversion.
  100. *
  101. * Note that this routine works with character pairs while building the
  102. * buffer.  If you specify an odd number of characters, this routine will 
  103. * round up the character count to the next higher even number, and then 
  104. * build the buffer with that many characters.  However, only the number
  105. * of characters you specify will actually be printed to the screen.
  106. *
  107. * ON ENTRY (on stack):
  108. *       ARG0 = address of the XTextSupport structure
  109. *       ARG1 = address of the text string
  110. *       ARG2 = character count
  111. *       ARG3 = x position for text output
  112. *       ARG4 = y position for text output
  113.  
  114. DREGS EQU    0      ; Offset to the pushed D-Registers
  115. DREGCOUNT EQU    6      ; How many D-Registers were pushed
  116. AREGS EQU    (DREGS+(DREGCOUNT*4)) ; Offset to the pushed A-Registers
  117. AREGCOUNT EQU    5
  118. FRONTPEN EQU    (AREGS+(AREGCOUNT*4))    ; Local variable
  119. BACKPEN  EQU    (FRONTPEN+2)    ; Local variable
  120. DRAWMODE EQU    (BACKPEN+2) ; Local variable
  121. XBLTSIZE EQU    (DRAWMODE+2)
  122. RETADDR  EQU    (XBLTSIZE+2)    ; Our return address
  123. ARG0  EQU    (RETADDR+4) ; Offset to passed arguments
  124. ARG1  EQU    (ARG0+4)
  125. ARG2  EQU    (ARG1+4)
  126. ARG3  EQU    (ARG2+4)
  127. ARG4  EQU    (ARG3+4)
  128.  
  129.  
  130.     LEA    -8(SP),SP        ; Reserve memory for local variables
  131.     MOVEM.L A2-A6/D2-D7,-(SP)
  132.  
  133.  
  134.     MOVE.L    ARG0(SP),A2    ; Get the XTextSupport structure address
  135.     MOVE.L    #_custom,A5    ; Get the address of the custom chip
  136.     MOVE.L    _GfxBase,A6    ; Load up A6 for graphics calls
  137.  
  138.  
  139. * Check the character count.
  140. * If it's zero, then split as there's nothing to do.
  141. * If it's less than zero, this is the signal that the programmer
  142. * wants *us* to figure out how long the string is.  Nice touch, eh?
  143. * If it's greater than zero, then presume it's valid.
  144.     MOVE.W    ARG2+2(SP),D2    ; Get the character count
  145.     BEQ    RETURN        ; and split if there's none to do
  146.     BGT    GOT_TEXT_COUNT    ; If greater than zero, then it's real
  147.  
  148.     MOVE.L    ARG1(SP),A4    ; Address of text string
  149.     MOVEQ.L    #-1,D2        ; Start with less than no characters
  150. 10$    ADDQ.W    #1,D2        ; Increment character count
  151.     TST.B    (A4)+        ; Test if next is end of text
  152.     BNE    10$        ; Branch if not
  153.  
  154.     MOVE.W    D2,ARG2+2(SP)    ; Save as character count
  155.  
  156. GOT_TEXT_COUNT:
  157. * The result of the following 3 instructions is created by the 2 below
  158. * I include this commentary to keep things from getting confusing
  159. *  ADDQ  #1,D2     ; to round up
  160. *  LSR.B #1,D2     ; Turn the char count into a pair count
  161. *  SUBQ.W    #1,D2     ; (-1 for DBRA of PAIRLOOP below)
  162.     SUBQ.B    #1,D2
  163.     LSR.B    #1,D2
  164.  
  165.  
  166.     CALLSYS OwnBlitter    ; Get that blitter
  167.  
  168.  
  169. * Get local copies of the pens, jazzed around to take the DrawMode into
  170. * account.  Namely, if JAM1 then the background pen is automatically zero,
  171. * and if the INVERSVID flag is set then swap the foreground/background pens
  172.  
  173.     CLEAR    D3        ; Save them as words
  174.     MOVE.B    xt_FrontPen(A2),D3 ; Load up the local front pen
  175.     CLEAR    D4        ; Start out presuming that back is zero
  176.     MOVE.B    xt_DrawMode(A2),D5 ; Test the draw mode 
  177.     MOVE.B    D5,D6        ; Save a copy
  178.     ANDI.W    #3,D5        ; Strip off INVERSVID (and any other) bit
  179.     MOVE.W    D5,DRAWMODE(SP)    ; and save the true drawmode
  180.     CMP.B    #RP_JAM1,D5    ; Is it JAM1?
  181.     BEQ    1$        ; If it's JAM1, leave the local back as zero
  182.     MOVE.B    xt_BackPen(A2),D4 ; else load up the local back pen
  183.  
  184. 1$    ANDI.B    #RP_INVERSVID,D6 ; Was INVERSVID bit set?
  185.     BEQ    2$        ; and skip if not
  186.     EXG    D3,D4        ; else exchange the pen registers
  187.  
  188. 2$
  189.     MOVE.W    D3,FRONTPEN(SP)    ; Save the local front pen
  190.     MOVE.W    D4,BACKPEN(SP)    ; Save the local back pen
  191.  
  192.  
  193.     MOVE.W    xt_CharHeight(A2),D6    ; Build the bltsize word
  194.     LSL.W    #6,D6        ; Height is shifted over as blitter likes it
  195.     MOVE.W    D6,XBLTSIZE(SP)    ; Save this partial for later
  196.  
  197.  
  198.     CMP.W    D3,D4        ; Are the pens equal?
  199.     BEQ    PLANESET    ; If so, skip building the planes
  200.  
  201.  
  202. * Wait 'til any blitting is done, and then initialize 
  203. * the blitter for my personal use ...
  204.     CALLSYS    WaitBlit    ; and wait for that baby to be free!
  205.  
  206.  
  207.     CLEAR    D3
  208.     MOVE.W    D3,bltamod(A5)    ; Set up the SRCA and SRCB modulos
  209.     MOVE.W    D3,bltbmod(A5)
  210.     SUBI.W    #1,D3
  211.     MOVE.W    D3,bltafwm(A5)    ; Masks are all set
  212.     MOVE.W    D3,bltalwm(A5)
  213.  
  214.     CLEAR    D3
  215.     MOVE.B    xt_MaxTextWidth(A2),D3
  216.     SUBQ.W    #2,D3
  217.     MOVE.W    D3,bltdmod(A5)
  218.     MOVE.W    #$0DFC,bltcon0(A5)    ; Use ABD, minterm is A or B, don't
  219.     MOVE.W    #$8000,bltcon1(A5)    ; shift A, shift B by 8
  220.  
  221.     MOVE.L    xt_NormalTextPlane(A2),D3 ; Address of the normal text plane
  222.  
  223.     MOVE.W    xt_FontSelect(A2),D6    ; Get the address of the font data
  224.     LSL.W    #2,D6
  225.     LEA    xt_FontData(A2),A3
  226.     ADD.W    D6,A3
  227.     MOVE.L    (A3),A3
  228.     MOVE.L    ARG1(SP),A4    ; Address of text string
  229.  
  230.     MOVE.W    xt_CharHeight(A2),D7
  231.  
  232.     MOVE.W    xt_Flags(A2),D6    ; Get the Flags
  233.     ANDI    #SLIM_XTEXT,D6    ; and test if the programmer wants SLIM_XTEXT
  234.     BNE    SLIM_CHARS    ; and go build the text the "slim" way if so
  235.                 ; else we're doing text the faster "fat" way
  236.  
  237.     MOVE.W    XBLTSIZE(SP),D6    ; Get the blit size partial
  238.     ORI    #1,D6        ; and make blit size one word wide
  239.  
  240.     CMPI    #8,D7        ; Can we do fast building?
  241.     BNE    SLOW_PAIRLOOP    ; If not 8, do it the "slow" way
  242.  
  243.  
  244. PAIRLOOP:
  245. * The normal text plane is constructed here.
  246. * Do as much pre-calculating as possible before actually waiting for the
  247. * blitter to be ready for re-use.
  248.  
  249.  
  250.     CLEAR    D4        ; Get the address of the font data of
  251.     MOVE.B    (A4)+,D4    ; the next character
  252.     LSL.W    #4,D4        ; (This presumes that each char is 16 bytes)
  253.     ADD.L    A3,D4
  254.  
  255.     CLEAR    D5        ; Get font data of next in pair (if there's
  256.     MOVE.B    (A4)+,D5    ; not really a second character (odd-numbered
  257.     LSL.W    #4,D5        ; string lengths) then this second move of
  258.     ADD.L    A3,D5        ; data will be unnecessary, but at least is
  259.                 ; harmless since the buffer is *always*
  260.                 ; pair-sized and the speed improvement is
  261.                 ; great when handling two characters at once)
  262.  
  263.     CALLSYS    WaitBlit    ; (this is redundant the first time through)
  264.  
  265.     MOVE.L    D4,bltapt(A5)
  266.     MOVE.L    D5,bltbpt(A5)
  267.     MOVE.L    D3,bltdpt(A5)
  268.  
  269.     MOVE.W    D6,bltsize(A5)    ; Bombs away!
  270.  
  271.     ADDQ.L    #2,D3        ; Advance destination pointer to next word
  272.  
  273.     DBRA    D2,PAIRLOOP
  274.  
  275. * Done, so go start setting up the planes 
  276.     BRA    PLANESET
  277.  
  278.  
  279. SLOW_PAIRLOOP:
  280. * The normal text plane is constructed here.
  281. * Done the "slow" way using a MULU because the character height isn't 8.
  282. * Do as much pre-calculating as possible before actually waiting for the
  283. * blitter to be ready for re-use.
  284.  
  285.  
  286.     CLEAR    D4        ; Get the address of the font data of
  287.     MOVE.B    (A4)+,D4    ; the next character
  288.     ADD.W    D4,D4
  289.     MULU    D7,D4        ; Offset * 2 * CharHeight
  290.     ADD.L    A3,D4
  291.  
  292.     CLEAR    D5        ; Get font data of next in pair (if there's
  293.     MOVE.B    (A4)+,D5    ; not really a second character (odd-numbered
  294.     ADD.W    D5,D5        ; string lengths) then this second move of
  295.     MULU    D7,D5
  296.     ADD.L    A3,D5        ; data will be unnecessary, but at least is
  297.                 ; harmless since the buffer is *always*
  298.                 ; pair-sized and the speed improvement is
  299.                 ; great when handling two characters at once)
  300.  
  301.     CALLSYS    WaitBlit    ; (this is redundant the first time through)
  302.  
  303.     MOVE.L    D4,bltapt(A5)
  304.     MOVE.L    D5,bltbpt(A5)
  305.     MOVE.L    D3,bltdpt(A5)
  306.  
  307.     MOVE.W    D6,bltsize(A5)    ; Bombs away!
  308.  
  309.     ADDQ.L    #2,D3        ; Advance destination pointer to next word
  310.  
  311.     DBRA    D2,SLOW_PAIRLOOP
  312.  
  313. * Done, so go start setting up the planes 
  314.     BRA    PLANESET
  315.  
  316.  
  317.  
  318. SLIM_CHARS:
  319. * OK, the programmer asked for SLIM_XTEXT, which is the half-size memory 
  320. * buffer for text to be built using the processor rather than the blitter
  321.  
  322.     MOVE.L    A5,-(SP)        ; Save A5 during the SLIM build
  323.  
  324.     CLEAR    D0            ; Build the byte-size modulo
  325.     MOVE.B    xt_MaxTextWidth(A2),D0
  326.     SUBQ    #1,D0
  327.  
  328.     MOVE.W    D7,D1            ; Build the line height (-1 for DBRA)
  329.     SUBQ    #1,D1
  330.     CMPI    #8,D7            ; Can we do fast building?
  331.     BNE    SLIM_SLOW_PAIRLOOP    ; If not 8, do it the "slow" way
  332.  
  333.  
  334. SLIM_PAIRLOOP:
  335. * The normal "slim" text plane is constructed here.
  336.  
  337.     CLEAR    D4        ; Get the address of the font data of
  338.     MOVE.B    (A4)+,D4    ; the next character
  339.     LSL.W    #3,D4        ; (This presumes that each char is 8 bytes)
  340.     ADD.L    A3,D4
  341.     MOVE.L    D4,A0
  342.  
  343.     CLEAR    D5        ; Get font data of next in pair (if there's
  344.     MOVE.B    (A4)+,D5    ; not really a second character (odd-numbered
  345.     LSL.W    #3,D5        ; string lengths) then this second move of
  346.     ADD.L    A3,D5        ; data will be unnecessary, but at least is
  347.     MOVE.L    D5,A1
  348.                 ; harmless since the buffer is *always*
  349.                 ; pair-sized and the speed improvement is
  350.                 ; great when handling two characters at once)
  351.  
  352.     MOVE.W    D1,D6        ; Build the bltsize word
  353.     MOVE.L    D3,A5
  354.  
  355. SLIM_BUILD:
  356.     MOVE.B    (A0)+,(A5)+
  357.     MOVE.B    (A1)+,(A5)
  358.     ADD.L    D0,A5
  359.     DBRA    D6,SLIM_BUILD
  360.  
  361.     ADDQ.L    #2,D3        ; Advance destination pointer to next word
  362.  
  363.     DBRA    D2,SLIM_PAIRLOOP ; Count down the character pairs to print 
  364.  
  365.     MOVE.L (SP)+,A5        ; Restore A5 at end of SLIM_BUILD 
  366.  
  367. * Done, so go start setting up the planes 
  368.     BRA    PLANESET
  369.  
  370.  
  371.  
  372. SLIM_SLOW_PAIRLOOP:
  373. * The normal "slim" text plane is slowly constructed here, slow because 
  374. * the characters are other than 8 lines tall.
  375.  
  376.     CLEAR    D4        ; Get the address of the font data of
  377.     MOVE.B    (A4)+,D4    ; the next character
  378.     MULU    D7,D4
  379.     ADD.L    A3,D4
  380.     MOVE.L    D4,A0
  381.  
  382.     CLEAR    D5        ; Get font data of next in pair (if there's
  383.     MOVE.B    (A4)+,D5    ; not really a second character (odd-numbered
  384.     MULU    D7,D5        ; string lengths) then this second move
  385.     ADD.L    A3,D5        ; will be unnecessary, but at least is
  386.     MOVE.L    D5,A1
  387.                 ; harmless since the buffer is *always*
  388.                 ; pair-sized and the speed improvement is
  389.                 ; great when handling two characters at once)
  390.  
  391.     MOVE.W    D1,D6        ; Build the bltsize word
  392.     MOVE.L    D3,A5
  393.  
  394. SLIM_SLOW_BUILD:
  395.     MOVE.B    (A0)+,(A5)+
  396.     MOVE.B    (A1)+,(A5)
  397.     ADD.L    D0,A5
  398.     DBRA    D6,SLIM_SLOW_BUILD
  399.  
  400.     ADDQ.L    #2,D3        ; Advance destination pointer to next word
  401.  
  402.     DBRA    D2,SLIM_SLOW_PAIRLOOP ; Count down the pairs to print 
  403.  
  404.     MOVE.L (SP)+,A5        ; Restore A5 at end of SLIM_BUILD 
  405.  
  406. * Done, so fall into starting setting up the planes 
  407.  
  408.  
  409.  
  410. PLANESET:
  411. * Well, that was quick, wasn't it.  Here all of the required planes (except
  412. * the bothersome Inverted Text Plane) are ready to go.    So let's figure
  413. * out how to initialize the plane pointers in the BitMap ...
  414.  
  415.     LEA    xt_TextBitMap(A2),A3
  416.     LEA    bm_Planes(A3),A4    ; Get address of first plane pointer
  417.  
  418.     CLEAR    D0            ; Set up the pen-test mask
  419.     MOVE.W    FRONTPEN(SP),D1        ; Fetch the foreground pen
  420.     MOVE.W    BACKPEN(SP),D2        ; and the background pen
  421.     CLEAR    D3
  422.     MOVE.B    bm_Depth(A3),D3        ; Get the BitMap depth ...
  423.     SUBQ.W    #1,D3            ; ... and set the loop count for DBRA
  424.     CLEAR    D4            ; Clear the Inverted flag
  425.  
  426.  
  427. PLANELOOP:
  428. * First, find out if the foreground/background pattern for this plane 
  429. * is 00, 01, 10 or 11.  based on the pattern, select the associated 
  430. * plane pointer for the BitMap
  431.     BTST    D0,D1        ; If the bit is set in the foreground pen
  432.     BNE    PAT_ONE        ; then go process 1x combinations
  433.  
  434. * Else we have a 0x combination.  Which one is it?
  435.     BTST    D0,D2        ; This time test the background pen
  436.     BNE    PAT_01        ; and if set then our pattern is 01
  437.  
  438. PAT_00:
  439.     MOVE.L    xt_AllClearPlane(A2),A3 ; This plane is the 00 plane
  440.     BRA    PLANE_STUFF
  441.  
  442. PAT_01:
  443. * The dreaded Inverse Text Plane selector.  If it doesn't exist yet,
  444. * I have to create it now.
  445.     MOVE.L    xt_InverseTextPlane(A2),A3 ; This plane is the inverse plane
  446.     TST.B    D4        ; Test our Inverted Plane flag
  447.     BNE    PLANE_STUFF    ; and skip this mess if it's already set
  448.                 ; else we'll have to invert it.
  449.     ADDQ.B    #1,D4        ; Set the inversion flag
  450.  
  451. * OK, so use the blitter inversion algorithm:  Dest = NOT SRC.
  452.  
  453.     CLEAR    D5
  454.     MOVE.B    xt_MaxTextWidth(A2),D5 ; Build the Group-of-2 values:
  455.     MOVE.W    ARG2+2(SP),D6
  456.     ADDQ.W    #1,D6        ; Get the first multiple of 2 that's greater
  457.     ANDI.W    #$FFFE,D6    ; than or equal to the character count, and
  458.     SUB.W    D6,D5        ; subtract that from the total buffer width
  459.                 ; to make the Group-of-2 row modulo
  460.  
  461.     LSR.W    #1,D6        ; Turn char count into pair count
  462.     OR.W    XBLTSIZE(SP),D6    ; and prepare for starting the blitter
  463.  
  464.     MOVEM.L    D0-D1,-(SP)
  465.     CALLSYS    WaitBlit    ; Wait for the blitter before I jam it.
  466.     MOVEM.L    (SP)+,D0-D1
  467.  
  468.     MOVE.L    xt_NormalTextPlane(A2),bltbpt(A5)
  469.     MOVE.L    A3,bltdpt(A5)
  470.  
  471.     MOVE.W    D5,bltbmod(A5)    ; Set up the SRCB and DEST modulos
  472.     MOVE.W    D5,bltdmod(A5)
  473.  
  474.     MOVE.W    #$0533,bltcon0(A5)
  475.     MOVE.W    #$0000,bltcon1(A5)
  476.  
  477.     MOVE.W    D6,bltsize(A5)    ; Bombs away!
  478.             
  479.     BRA    PLANE_STUFF
  480.  
  481.  
  482. PAT_ONE:
  483. * We've got a 1x pattern.  Which one do you suppose it is?  Hmm ...
  484.     BTST    D0,D2        ; This time, test the back pen only
  485.     BNE    PAT_11
  486.  
  487.  
  488. PAT_10:
  489. * Normal Text Plane?  No problem.
  490.     MOVE.L    xt_NormalTextPlane(A2),A3
  491.     BRA    PLANE_STUFF
  492.  
  493. PAT_11:
  494.     MOVE.L    xt_AllSetPlane(A2),A3    ; This plane must have all bits set
  495.  
  496. * and fall into ...
  497.  
  498.  
  499. PLANE_STUFF:
  500. * OK, so A3 has the address of this plane's data.  Stuff that baby
  501. * into the BitMap structure.
  502.     MOVE.L    A3,(A4)+
  503.  
  504.     ADDQ    #1,D0        ; Advance our mask to the next position
  505.  
  506.     DBRA    D3,PLANELOOP    ; Loop on the depth of the BitMap
  507.  
  508.  
  509. * Now, all done with the private use of the blitter.  Here, I would prefer
  510. * to retain exclusive use of the blitter even throughout the call to
  511. * BlitBMRP below, but the system won't let me.  Too bad!
  512.  
  513.  
  514.     CALLSYS    DisownBlitter
  515.  
  516.  
  517. * Well, now the BitMap is all ready to blast out our new line
  518. * of text.  Wasn't that fun?  Now the simple final stroke:  zap that
  519. * data into the RastPort, using the ever-popular, cleverly-named
  520. * BltBitMapRastPort function (if Dale wasn't so good, I'd suggest
  521. * that we take him out and shoot him for that name).
  522. *
  523. * BlitBMRP wants:
  524. *
  525. * A0 = Source BitMap  
  526. * A1 = Destination RastPort
  527. * A6 = GfxBase
  528. *
  529. * D0 = Source X
  530. * D1 = Source Y
  531. * D2 = Destination X
  532. * D3 = Destination Y
  533. * D4 = Pixel Width of block to be moved
  534. * D5 = Scan-line Height of block to be moved
  535. * D6 = Minterm
  536.  
  537.     CLEAR    D5
  538.     MOVE.W    xt_CharHeight(A2),D5    ; Height of transfer
  539.  
  540.     MOVE.W    #XTEXT_CHARWIDTH,D4    ; Create the blit width ...
  541.     MOVE.W    ARG2+2(SP),D3        ; Character count
  542.     MULU    D3,D4            ; Width of transfer (creates LONG)
  543.  
  544.     MOVE.L    ARG4(SP),D3        ; Get the Y position into D3
  545.     MOVE.L    ARG3(SP),D2        ; Get the X position into D2
  546.  
  547.     CLEAR    D1            ; Source x and y are 0
  548.     CLEAR    D0
  549.  
  550.     MOVE.L    xt_OutputRPort(A2),A1    ; and get the RPort of the display
  551.  
  552.     LEA    xt_TextBitMap(A2),A0    ; Get the address of the BitMap arg
  553.  
  554. * The DrawMode defines what minterm we use and which routine we call.
  555.     CMP.W    #RP_JAM1,DRAWMODE(SP)    ; Are we doing JAM1?
  556.     BEQ    DO_JAM1
  557.  
  558. * The DrawMode can be JAM2 or COMPLEMENT.  Which is it, hmm?
  559.     MOVE.L    #$C0,D6            ; Minterm (simple transfer) for JAM2
  560.     CMP.W    #RP_JAM2,DRAWMODE(SP)    ; Is it really JAM2?
  561.     BEQ    BBMRP            ; Branch if so
  562.  
  563.     MOVE.L    #$60,D6            ; Only other is complement mode
  564.  
  565. BBMRP:
  566.     CALLSYS    BltBitMapRastPort    ; Do the normal (fast) BBMRP
  567.     BRA    RETURN
  568.  
  569.  
  570. DO_JAM1:
  571. * Call BltMaskBitMapRastPort, which is the same as BBMRP except that a
  572. * mask is used to cookie-cut the source into the destination.
  573. * JAM1 requires a mask, because JAM1 is cookie-cut!
  574. * The mask goes into A2.  If either pen was non-zero then we built 
  575. * the normal plane so use that as the mask,
  576. * else use the AllZeroPlane for the mask (which produces zip imagery!).
  577. * The minterm sez:  cut me in, daddio.
  578.  
  579.     MOVE.B    xt_DrawMode(A2),D6    ; Was this inverse video?
  580.     ANDI.B    #RP_INVERSVID,D6
  581.     BNE    1$            ; If so, use inverse JAM1 minterm
  582.     MOVE.L    #$E0,D6            ; else use normal JAM1 minterm
  583.     BRA    2$
  584.  
  585. 1$    MOVE.L    #$B0,D6
  586.  
  587. 2$    TST.W    FRONTPEN(SP)        ; Was the front pen zero?
  588.     BNE    3$            ; If not then get Normal for mask
  589.     TST.W    BACKPEN(SP)        ; Was the back pen zero?
  590.     BNE    3$            ; If not then get Normal for mask
  591.     MOVE.L    xt_AllClearPlane(A2),A2    ; AllClearPlane is the mask
  592.     BRA    4$
  593.  
  594. 3$    MOVE.L    xt_NormalTextPlane(A2),A2 ; use the plane as the mask
  595.  
  596. 4$    CALLSYS    BltMaskBitMapRastPort    ; Do the not-as-fast BMBMRP
  597.  
  598.  
  599.  
  600. RETURN:
  601.     MOVEM.L    (SP)+,A2-A6/D2-D7
  602.     LEA    8(SP),SP        ; Release memory of local variables
  603.  
  604.     RTS
  605.  
  606.  
  607.     END
  608.  
  609.  
  610.